package com.aaron.development.projectdevelopment;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;

import com.google.wave.api.AbstractRobotServlet;
import com.google.wave.api.Blip;
import com.google.wave.api.Event;
import com.google.wave.api.EventType;
import com.google.wave.api.RobotMessageBundle;
import com.google.wave.api.TextView;
import com.google.wave.api.Wavelet;

/**
 * TODO Still need to do the following:
 * 		- Make sure the waveletId, waveId are used so we only ban the user for the current wave
 * 		- Make sure that we only enter the bannedUser once
 * 		- Go over the system and clean up, there has been no refactoring yet
 * 
 * @author aaron
 *
 */

@SuppressWarnings("serial")
public class ProjectCollaberationServlet extends AbstractRobotServlet {
	
	@Override
	public void processEvents(RobotMessageBundle bundle) {
		Wavelet wavelet = bundle.getWavelet();
		              
		if (bundle.wasSelfAdded()) {
			Blip blip = wavelet.appendBlip();
			TextView textView = blip.getDocument();
			textView.append("I'm alive!");
		}
		
		PersistenceManager pm = PMF.get().getPersistenceManager();
		
		for (Event e: bundle.getEvents()) {
			if (e.getType() == EventType.WAVELET_PARTICIPANTS_CHANGED) {    
				Blip blip = wavelet.appendBlip();
				TextView textView = blip.getDocument();
				textView.append("Hi, everybody! I will be moderating this wave.");
			}
			
			// If blip contributors have changed make sure that we don't have a banned user tying to make changes
			if (e.getType() == EventType.BLIP_CONTRIBUTORS_CHANGED) {
				blipContributorsChanged(e, pm);
			}
			
			if (e.getType() == EventType.BLIP_SUBMITTED) {
				// Check if we need to stop a banned user from editing
				String filtersBlip = "blipId == blipId__ && waveId == waveId__";
				Query queryBlip = pm.newQuery(BlipChangeData.class, filtersBlip);
				queryBlip.declareParameters("String blipId__, String waveId__");
				List<BlipChangeData> changeBlips = (List<BlipChangeData>) queryBlip.executeWithArray(new Object[] {e.getBlip().getBlipId(), wavelet.getWaveId()});
				
				if (changeBlips.size() > 0) {
					BlipChangeData originalBlip = changeBlips.get(0);
					e.getBlip().getDocument().replace(originalBlip.getBlipText());
				}
				
				
				// Other stuff
				Blip submitted_blip = e.getBlip();
				
				// Ban the user if that is what is requested
				if ( wavelet.getCreator().equals( submitted_blip.getCreator()) ) {
					banUser(wavelet, submitted_blip, pm);
				}
				
				String filters = "userId == userId__ && waveId == waveId__";
				Query query = pm.newQuery(BannedUser.class, filters);
				query.declareParameters("String userId__, String waveId__");
				List<BannedUser> bannedUsers = (List<BannedUser>) query.executeWithArray(new Object[] {e.getBlip().getCreator(), wavelet.getWaveId()});
				
				if ( bannedUsers.size() > 0) {					
					e.getBlip().delete();
				} 
				
				
			} // End if event type check
		} // End event for loop
		
	}

	private void blipContributorsChanged(Event e, PersistenceManager pm) {
		List<String> participants = (List<String>) e.getBlip().getContributors();
		String waveId = e.getWavelet().getWaveId();
		
		String filters = "waveId == waveId__";
		Query query = pm.newQuery(BannedUser.class, filters);
		query.declareParameters("String waveId__");
		List<BannedUser> bannedUsers = (List<BannedUser>) query.executeWithArray(new Object[] {waveId});
		
		// Now we need to check if any of the added participants are banned users.
		List<String> bannedParticipants = new ArrayList<String>();
		for (BannedUser bannedUser : bannedUsers) {
			if (participants.contains(bannedUser.getUserId())) {
				bannedParticipants.add(bannedUser.getUserId());
			}
		}
		
		// If we have a banned user stop the change.
		if (bannedParticipants.size() > 0) {
			Blip blip = e.getWavelet().appendBlip();
			TextView textView = blip.getDocument();
			textView.append("We have a banned user trying to edit.");
			
			for (String bannedParticipant : bannedParticipants) {
				String blipText = e.getBlip().getDocument().getText();
				
				// TODO Update if we already have one.
				BlipChangeData blipChange = new BlipChangeData(e.getBlip().getBlipId(), blipText, waveId);
				
				e.getBlip().getContributors().remove(bannedParticipant);				
			}

		}
	}
	
	/**
	 * TODO Go over this method and clean it up.
	 * @param wavelet
	 * @param submitted_blip
	 */
	private void banUser(Wavelet wavelet, Blip submitted_blip, PersistenceManager pm) {
		// TODO Stop someone from saving edits if they have been banned. Basically, make a blip read only.
		// TODO Clean up this regular expression matching, if needed
		String re = "ban:.+@.+\\.com";
		Pattern p = Pattern.compile(re, Pattern.DOTALL);
		Matcher m = p.matcher(submitted_blip.getDocument().getText());

		while ( m.find() ) {
			String bannedText = m.group(0);
			// TODO See if we can clean up the regular expression so that we don't have to do this string splitting here.
			String bannedUser = bannedText.split("ban:")[1];
			Blip blip = wavelet.appendBlip();
			TextView textView = blip.getDocument();
			
			Date date = new Date();
			BannedUser bannedUserData = new BannedUser(bannedUser, date, wavelet.getWaveId());												
			
			// TODO Check out the Wave examples online to see a good way to move this out of here. Remove as much DB handling code from here
			// as possible.
			try {
				pm.makePersistent(bannedUserData);
				textView.append("The user: " 
						+ bannedUserData.getUserId() 
						+ " has been banned.");
			} finally {
				pm.close();
			} // End try/catch	
			
		} // End while loop									
	}
	
}
